/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package XML;

import Offer.Hotel;
import Offer.Offer;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.Characters;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

/**
 *
 * @author Dopsilon
 */
public class XMLReader {
    private static XMLReader theReader = null;
    private Calendar lastUpdate;
    private final XMLInputFactory factory;
    private final XMLEventReader eventReader;
    public static XMLReader getInstance() throws FileNotFoundException, 
            XMLStreamException{
        if (theReader == null) {
            theReader = new XMLReader();
            return theReader;            
        } else {
            return theReader;
        }
    }
    public XMLReader() throws FileNotFoundException, XMLStreamException {
        
        String filename = "src/XML/test.xml";
        this.factory = XMLInputFactory.newFactory();
 
        this.eventReader = this.factory.createXMLEventReader(filename,
            new FileInputStream(filename));     
        
    }
    
    public boolean hasNext() {
       return this.eventReader.hasNext();
    }
   
    public Offer buildOffer() throws XMLStreamException, ParseException{
        Offer xmlOffer = new Offer();
        Hotel theHotel = new Hotel();
        
        while(this.eventReader.hasNext()){            
            
            XMLEvent event = this.eventReader.nextEvent();            
            if (event.isEndElement()) {
                EndElement end = event.asEndElement();
                if (end.getName().getLocalPart().equals(Tags.OFFER)) {
                    break;
                } else if (end.getName().getLocalPart().equals(Tags.LMSDATA)) {
                   
                    return null;
                }
               
            } else {
                
                tagSorting(xmlOffer,theHotel, event);
            }
            
        }
        xmlOffer.setHotel(theHotel);
        return xmlOffer;       
    }
    
    private void tagSorting(Offer xmlOffer, Hotel theHotel, XMLEvent event)
            throws XMLStreamException, ParseException{
        
        if (event.isStartElement()) {
            StartElement start = event.asStartElement();
            String tagName = start.getName().getLocalPart();
            switch(tagName){
                case Tags.BOOKLINK:
                  //  System.out.println("Booklink: ");
                    xmlOffer.setBookLink(getValue(tagName));
                    break;
                case Tags.CAMPAINGNAME:
                   // System.out.println("Campaign name:");
                    xmlOffer.setCampaignName(getValue(tagName));
                    break;
                case Tags.CITYNAME:
                    // System.out.println("City name: ");
                     xmlOffer.setCityName(getValue(tagName));
                    break;
                case Tags.CONTENTLINK:
                    // System.out.println("Contentlink: ");
                     xmlOffer.setContentLink(getValue(tagName));
                    break;
                case Tags.CURRENTPRICE:
                   //  System.out.println("CurrentPrice: ");
                    xmlOffer.setCurrentPrice(getValue(tagName));
                    break;
                case Tags.DEPARTURENAME:
                    // System.out.println("Departurename: ");
                    xmlOffer.setDepartureName(getValue(tagName));
                    break;
                case Tags.DESTINATIONNAME:
                   //  System.out.println("destination: ");
                    xmlOffer.setDestinationName(getValue(tagName));
                    break;
                case Tags.FLIGHTEXTERN:
                   //  System.out.println("FlightExt: ");
                    xmlOffer.setFlightExtern(getValue(tagName));
                    break;
                case Tags.HOTELGRADE:
                     //System.out.println("Booklink: ");
                    theHotel.setGrade(getDouble(tagName));
                    break;
                case Tags.HOTELGRADESTRING:
                    // System.out.println("Booklink: ");
                    theHotel.setHotelGradeString(getValue(tagName));
                    break;
                case Tags.HOTELIMAGE:
                     //System.out.println("Booklink: ");
                    theHotel.setImageURL(getValue(tagName));
                    break;
                case Tags.HOTELNAME:
                     //System.out.println("Booklink: ");
                    theHotel.sethName(getValue(tagName));
                    break;
                case Tags.JOURNEYLENGTH:
                    // System.out.println("Booklink: ");
                    xmlOffer.setJourneyLength(getInteger(tagName));
                    break;
                case Tags.JOURNEYLENGTHWEEKS:
                    // System.out.println("Booklink: ");
                    xmlOffer.setJourneyLengthWeeks(getInteger(tagName));
                    break;
                case Tags.NOOFSEATSREMAINING:
                    // System.out.println("Booklink: ");
                    xmlOffer.setNoOfSeatsRemaining(getInteger(tagName));
                    break;  
                case Tags.OUTDATE:
                    //System.out.println("OutDate");
                    xmlOffer.setOutDate(getDate(tagName));
                    break;
                case Tags.ROOMDESCRIPTION:
                    //System.out.println("Room Desc");
                    xmlOffer.setRoomDescription(getValue(tagName));
                    break;
                case Tags.ORIGINALPRICE:
                    //System.out.println("Original Price");
                    xmlOffer.setOriginalPrice(getValue(tagName));
                    break;
                case Tags.PRICECURRENCY:
                    //System.out.println("Price Currency");
                    xmlOffer.setPriceCurrency(getValue(tagName));
                    break;
                case Tags.OFFER:
                    
                    break;
                case Tags.LMSDATA:
                    getTime(start);
                   
                    break;
                default: 
                    System.out.println(event.toString());
                    break;
            }        
            
        }
        
    }
    
    private void getTime(StartElement event) throws XMLStreamException, ParseException{
        Attribute attributeByName = event.getAttributeByName(new QName("LastUpdate"));
        this.lastUpdate = Calendar.getInstance();
        SimpleDateFormat timeStamp = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timeStrign = attributeByName.getValue();
        this.lastUpdate.setTime(timeStamp.parse(attributeByName.getValue()));
        
        
    }
   
    private Integer getInteger(String element) throws XMLStreamException {
        Integer inputValue = 0;
        while(this.eventReader.hasNext()){
            if(this.eventReader.peek().isEndElement()){
                EndElement end = this.eventReader.peek().asEndElement();
                if(end.getName().getLocalPart().equals(element)){
                    break;                            
                }               
                
            }
            XMLEvent event = this.eventReader.nextEvent();
            
            if (event.isCharacters()) {
                Characters values = event.asCharacters();
                if(values.getData().contains("\n")){
                    continue;
                }
                inputValue = Integer.valueOf(values.getData());
            }   
            
        }        
        return inputValue;
    }
    
    private String getValue(String element) throws XMLStreamException{
        String inputValue = "";
       
        while(this.eventReader.hasNext()){
            if(this.eventReader.peek().isEndElement()){
                EndElement end = this.eventReader.peek().asEndElement();
                if(end.getName().getLocalPart().equals(element)){
                    break;                            
                }               
                
            }
            XMLEvent event = this.eventReader.nextEvent();
            if (event.isCharacters()) {
                Characters values = event.asCharacters();
                if(values.getData().contains("\n")){
                    continue;
                }
                inputValue += values.getData();
            }   
            
        }        
        return inputValue;
    }

    private Calendar getDate(String tagName) throws XMLStreamException, ParseException {
        Calendar returnDate = Calendar.getInstance();
       
        while(this.eventReader.hasNext()){
            if(this.eventReader.peek().isEndElement()){
                EndElement end = this.eventReader.peek().asEndElement();
                if(end.getName().getLocalPart().equals(tagName)){
                    break;                            
                }               
                
            }
            XMLEvent event = this.eventReader.nextEvent();
            if (event.isCharacters()) {
                Characters values = event.asCharacters();
                if(values.getData().contains("\n")){
                    continue;
                }
                String dateSplit[] = values.getData().split("-");
                
                returnDate.set(Integer.valueOf(dateSplit[0]),
                        Integer.valueOf(dateSplit[1]),
                        Integer.valueOf(dateSplit[2]));
            }   
            
        }       
       // System.out.println(returnDate.toString());
        return returnDate;
    }

    private Double getDouble(String tagName) throws XMLStreamException {
        Double inputValue = new Double(0);
        while(this.eventReader.hasNext()){
            if(this.eventReader.peek().isEndElement()){
                EndElement end = this.eventReader.peek().asEndElement();
                if(end.getName().getLocalPart().equals(tagName)){
                    break;                            
                }               
                
            }
            XMLEvent event = this.eventReader.nextEvent();
            
            if (event.isCharacters()) {
                Characters values = event.asCharacters();
                if(values.getData().contains("\n")){
                    continue;
                }
                if(values.getData().contains(",")){
                    String[] splitString = values.getData().split(",");
                    
                    inputValue = new Double(splitString[0]+"."+splitString[1]);
                } else {
                    inputValue = new Double(values.getData());
                }
                
                
            }   
            
        }        
        return inputValue;
    }
}